/*
 * AR1511_NMEA.c
 *
 *  Created on: Dec 17, 2010
 *      Author: root
 */

#include "../includes.h"


//SYS_		SYSTEM;

//#ifndef NULL
//#define NULL ((void *)0)
//#endif
//
//#define YES 1
//#define NO	0

int FR_cnt=0;
int fr_fixinfo=0;
int fr_restart_mode = 0;
//extern int zero_tracking ;

#define FR_RESTART_KNOWN_POS	1
#define FR_RESTART_AVG_POS		2

char gpgga_fix;


//char *cmdNMEA01="$PUNV,SET,00,0000,00,1000,9600,FF*7D\r\n";
//char *cmdNMEA01="$PUNV,SET,00,0000,00,1000,9600,7F*0C\r\n";
//int bRcvZDA=0;
int bRcvTypeF1000c=0;




cmdNMEA_ cmdNMEA[10]=
{
	//{nmeaTo9600, "$PUNV,SET,00,0000,00,1000,9600,FF*7D\r\n" }
	{nmeaOutput, 		"$PUNV,SET,00,0000,00,1000,38400,DD*4D\r\n" }
	//,{nmeaResetAll,		"$PUNV,START,BFF*1F\r\n"}
	//$PUNV,START,ALL*1C
	,{nmeaResetAll,		"$PUNV,START,ALL*1C\r\n"}
	,{nmeaResetCold, 	"$PUNV,START,COLD*59\r\n"}
	,{nmeaResetWarm, 	"$PUNV,START,WARM*54\r\n"}
	,{nmeaResetHot, 	"$PUNV,START,HOT*0E\r\n"}
	,{nmeaEnd,NULL}
	,
};

void SendCommandToF1000c(int cmd)
{
	int i=0;
	for(i=0;i<10 && cmdNMEA[i].str != NULL; i++ )
	{
		if( cmd == i){
			write(fdEB,cmdNMEA[i].str,strlen(cmdNMEA[i].str));
			//printf(cmdNMEA[i].str);
		}
	}
}

int SendNmeaToF1000c(char *s1)
{
	int i=0;
	unsigned char buf[200];
	unsigned char buf1[200];
	unsigned char d1=0;
	unsigned char *s;
	int len;
	int bStarExist=0;

	strcpy(buf1,s1);
	s=buf1;
	len=strlen(s);

	if(len> 200-10 ) return 0;

	if( s[len-1] =='*' ){ len--; bStarExist=1; }

	for( i = 1; i < len; i++ ){	d1 ^= s[i];	}

	if( bStarExist ) sprintf(buf,"%s%02X\r\n",s,d1);
	else sprintf(buf,"%s*%02X\r\n",s,d1);

	//printf(buf);
	write(fdEB,buf,strlen(buf));
	return 0;
}


int nmea_msg_rcvd( char* buf, int offset, int len)
{
int i1;
char* tokens[32];
char* result;
char max_token;
int advance;
char strTemp[300];
	advance = nmea_crc_validate(buf, offset, len);
	if(advance == -1){return 0;}

	tokens[0] = buf+1;

//	printf("[%03d] nmea      : %s\r\n", (int)(elapsed_sync.nanoseconds/1000000), buf);

	for(i1=0;i1<32;i1++){
		result = strchr(tokens[i1], ',');
		if(result == NULL) {
			result = strchr(tokens[i1], '*');
			if(result != NULL) *result = 0;
			break;
		}

		*result = 0;
		tokens[i1+1] = result+1;
	}

	max_token = i1+1;

	if((max_token == 1) || (max_token >= 32)){return 0;}

	if(strcmp("GPGGA",tokens[0])==0){
		nmea_unpack_gpgga(tokens,max_token);
	}
	else if(strcmp("GPZDA",tokens[0])==0){
//		printf("\n>>>>>>ZDA\n");
//		sprintf(MESG,  "\n$$$$ZDA,%s\n", tokens[1]);
//		TransmitMessage((BYTE*)MESG,PORT_CONTROL);
		nmea_unpack_gpzda(tokens,max_token);
	}
	else if(strcmp("GPGSA",tokens[0])==0){
		nmea_unpack_gpgsa(tokens, max_token);
	}
	else if(strcmp("GPGSV",tokens[0])==0){
		nmea_unpack_gpgsv(tokens, max_token);
	}
	else if(strcmp("GPDTM",tokens[0])==0){
		nmea_unpack_gpdtm(tokens, max_token);
	}
	else if(strcmp("PUNV",tokens[0])==0){
		//bRcvZDA = 1;
	}

	if( iLsiDebugVariable == 3333 ) printf("%s\n",tokens[0]);

//	if(strcmp("GPGSA",tokens[0])!=0) return advance;
//	int i;
//	//sprintf(MESG,  "\n");
//	printf(MESG,  "\n");
//	for( i=0; i< max_token; i++)
//	{
//		printf(strTemp,  ",%s", tokens[i]);
//	}
//	buf_f1000c.Rx_Match_TimeOut = 0;
	if(!strcmp("PUNV",tokens[0]) && !strcmp("START",tokens[1]) ){ printf("%s,%s,%s\n",tokens[0],tokens[1],tokens[2]); }
	return advance;
}


int nmea_crc_validate(unsigned char* buf, int offset, int len)
{
int i;
int start=0;
int end=0;
char chk_em=0, chk_gn=0;
int length = len-offset;

	for(i=0;i<length;i++){
		if((start != 0) && (buf[i] != '*')) {chk_gn ^= buf[i]&0xFF;}

		if(buf[i] == '$') {start = i+1;}
//		if(buf[i] == '#') {start = i+1;}
		else if((buf[i] == ',') && (start != 0) && (end == 0)) {end = i;}
		else if((buf[i] == '*') && (start != 0) && (end != 0))
		{
			if(length>=i+2){
				buf[i+3]=0;

				chk_em = strtoul(&buf[i+1], NULL, 16);
				if(chk_gn == chk_em){return i+1;}
				else{
					return -1;
				}
			}
		}
	}
	return -1;

}

#define my_atof(x) atof(x)

//double my_atof (const char *string)
//{
//    double result;
//
//    /* this still does not detect '12ab' as invalid */
//    if (sscanf(string, "%lf", &result) != 1) return 0;
//
//    return result;
//}


//$GPDTM,15,11,01,04,0,1,*66
int nmea_unpack_gpdtm(char** tokens, int max_token)
{
	char c1,c2,c3,c4;
	int i1,i2,i3;
	EB_	*EB = &SYSTEM.EB;
	TS_	*TRACK = &SYSTEM.TRACK;
	POS_	*POSITION = &SYSTEM.POSITION;
	PHP_	*PHP = &SYSTEM.EB.PHP;
	char *p;

	int degree, minute, frac;
	long lat,lon;
	int dop;
	long int hei;
	double df;

	i1=max_token-1;
	i2=i3=0;

	if(max_token < 6) {return 0;}

	SYSTEM.TIME.LEAPSECOND = (signed char) atoi(tokens[1]);

    EB->TIME.YEAR 	= (WORD)( atoi(tokens[2])+2000 );
    EB->TIME.MONTH 	= (BYTE)  atoi(tokens[3]);
    EB->TIME.DAY 	= (BYTE)  atoi(tokens[4]);

	if( atoi(tokens[5]) ) 		SYSTEM.EB.ANTENNA = ANTENNA_OPENED;  //open
	else if( atoi(tokens[6]) ) 	SYSTEM.EB.ANTENNA = ANTENNA_SHORTED; //short
	else 						SYSTEM.EB.ANTENNA = ANTENNA_OK;

   	if( (!EB->bRcvZDA) && SYSTEM.TIME.LEAPSECOND ){
   		EB->bRcvZDA = 1;
		EB->almanac_step = EB_SET_LEAPSECOND;
		EB->STATUS = EB_STATUS_RUN;
		EB->TASK = OFF;
		EB->LockedCounter = 0;

		EB->once_receiver_detect = ON;

		MessageOut("EB-RUN\r\n");
		LogIt(LOG_CATA1_NORM, LOG_CATA2_NOTHING, LOG_EB_In,0);
   	}


   	//if( iLsiDebugVariable == 30004 )
   	if( iLsiDebugVariable == 3333 )
		printf("\n %4d/%02d/%02d,leap:%02d,  ant:%d >>> \n"
				,(int)EB->TIME.YEAR, (int)EB->TIME.MONTH, (int)EB->TIME.DAY
				, (int)SYSTEM.TIME.LEAPSECOND, SYSTEM.EB.ANTENNA
		);
   	if( iLsiDebugVariable == 3337 || SYSTEM.IO.CTRL_PORT.MODE == UDEBUG5 ){
   		if( GC.RunningTime%60 == 0 ){
   			printf("%c[1J%c[0J" ,0x1B,0x1B );
   		}
   		printf("%c[1;1H" ,0x1B);
   	}
   	return 0;
}


int prevZDAsec=0;
void nmea_unpack_gpzda(char** tokens, int max_token)
{
	char c1,c2,c3,c4;
	int i1,i2,i3;
	int hour,min,sec;
	time_   time;

	EB_	*EB = &SYSTEM.EB;
	TS_	*TRACK = &SYSTEM.TRACK;
	POS_	*POSITION = &SYSTEM.POSITION;
	PHP_	*PHP = &SYSTEM.EB.PHP;

	int degree, minute, frac;
	long lat,lon;
	int dop;
	long int hei;

	i1=max_token-1;
	i2=i3=0;

	if(max_token < 1) {return;}

    EB->TIME.YEAR 	= (WORD)(WORD)atoi(tokens[1+3]);
    EB->TIME.MONTH 	= (BYTE)atoi(tokens[1+2]);
    EB->TIME.DAY 	= (BYTE)atoi(tokens[1+1]);

//    time.YEAR = (WORD)atoi(tokens[1+3]);
//	time.MONTH = (BYTE)atoi(tokens[1+2]);
//	time.DAY = (BYTE)atoi(tokens[1+1]);

//	i1 = ((*tokens[1+0] - '0')*10) + (*(tokens[1+0]+1) - '0');
//	time.HOUR = (BYTE)i1;
//	i1 = ((*(tokens[1+0]+2) - '0')*10) + (*(tokens[1+0]+3) - '0');
//	time.MINUTE = (BYTE)i1;
//	i1 = ((*(tokens[1+0]+4) - '0')*10) + (*(tokens[1+0]+5) - '0');
//	time.SECOND = (BYTE)i1;
//	//increase_second(&EB->TIME, SYSTEM.TIME.LEAPSECOND);
//	SYSTEM.TIME.LEAPSECOND = 15 ;
//	increase_second(&time, 15);
//
//   	printf("\n##:%2d,%2d,> "
//   			", %2d ,%2d,>"
//   			", %2d:%2d,%2d"
//   			,TimeSliceCounter, time.SECOND!=SYSTEM.TIME.GPS.SECOND
//   			, time.SECOND ,SYSTEM.TIME.GPS.SECOND
//   			,SYSTEM.TIME.GPS.HOUR, SYSTEM.TIME.GPS.MINUTE, SYSTEM.TIME.GPS.SECOND );


//   	i1 = ((*tokens[1+0] - '0')*10) + (*(tokens[1+0]+1) - '0');
//   	EB->TIME.HOUR = (BYTE)i1;
//   	i1 = ((*(tokens[1+0]+2) - '0')*10) + (*(tokens[1+0]+3) - '0');
//   	EB->TIME.MINUTE = (BYTE)i1;
//   	i1 = ((*(tokens[1+0]+4) - '0')*10) + (*(tokens[1+0]+5) - '0');
//   	EB->TIME.SECOND = (BYTE)i1;
//   	//increase_second(&EB->TIME, SYSTEM.TIME.LEAPSECOND);
//   	increase_second(&EB->TIME, 15);

//	sprintf(MESG,  "\nrcv ZDA \n" );
//	TransmitMessage((BYTE*)MESG,PORT_CONTROL);
	SYSTEM.TIME.LEAPSECOND = 15;
 	if( (!EB->bRcvZDA) && SYSTEM.TIME.LEAPSECOND ){
   		EB->bRcvZDA = 1;
		EB->almanac_step = EB_SET_LEAPSECOND;
		EB->STATUS = EB_STATUS_RUN;
		EB->TASK = OFF;
		EB->LockedCounter = 0;

		EB->once_receiver_detect = ON;

		MessageOut("EB-RUN\r\n");
		LogIt(LOG_CATA1_NORM, LOG_CATA2_NOTHING, LOG_EB_In,0);
   	}

}



int ar1511_model_cnt=0;
int ar1511_model_cnt2=0;
int prevTODSec=0;
void nmea_unpack_gpgga(char** tokens, int max_token)
{
	char c1,c2,c3,c4;
	int i1,i2,i3;
	EB_	*EB = &SYSTEM.EB;
	TS_	*TRACK = &SYSTEM.TRACK;
	POS_	*POSITION = &SYSTEM.POSITION;
	PHP_	*PHP = &SYSTEM.EB.PHP;
	char *p;

	int degree, minute, frac;
	long lat,lon;
	int dop;
	long int hei;
	double df;

	i1=max_token-1;
	i2=i3=0;

	if(max_token < 9) {return;}

	if( (!EB->bRcvZDA) ){
		//write(fdEB,cmdNMEA01,strlen(cmdNMEA01));
		//printf("try Send ZDA cmd\r\n");
//		sprintf(MESG,  "\n try Send ZDA cmd\n" );
//		TransmitMessage((BYTE*)MESG,PORT_CONTROL);
	}

	if(++ar1511_model_cnt>2)
	{
		ar1511_model_cnt = 10;
		EB->model_name = "F1000cRcu";
		bRcvTypeF1000c = 1;

	}

	EB->RxCheckCounter = 0;

	//,GPGGA,031504.000,3625.8386,N,12723.6508,E,1,11,0.8,75.92,M,0.00,M,,
	int i;
   	i = ((*tokens[1+0] - '0')*10) + (*(tokens[1+0]+1) - '0');
   	EB->TIME.HOUR = (BYTE)i;
   	i = ((*(tokens[1+0]+2) - '0')*10) + (*(tokens[1+0]+3) - '0');
   	EB->TIME.MINUTE = (BYTE)i;
   	i = ((*(tokens[1+0]+4) - '0')*10) + (*(tokens[1+0]+5) - '0');
   	EB->TIME.SECOND = (BYTE)i;

   	if( SYSTEM.TIME.LEAPSECOND ) increase_second_amount(&EB->TIME,  (signed char)SYSTEM.TIME.LEAPSECOND);
   	else increase_second_amount(&EB->TIME, 15);

   	i = EB->TIME.SECOND - prevTODSec;
   	if( i < 0 ) i+=60;

   	if( iLsiDebugVariable == 3334 )
		printf("<%2d> "
				", %2d:%2d,%2d"
				,TimeSliceCounter
				,EB->TIME.HOUR, EB->TIME.MINUTE, EB->TIME.SECOND
		);

   	prevTODSec = EB->TIME.SECOND;
   	//increase_second(&EB->TIME, SYSTEM.TIME.LEAPSECOND);
   	//increase_second(&EB->TIME, 15);

//	p = tokens[1+1];
//	degree = (*p-'0')*10 + (*(p+1)-'0');
//	minute = (*(p+2)-'0')*10 + (*(p+3)-'0');
//	frac = (*(p+5)-'0')*1000 + (*(p+6)-'0')*100 +
//			(*(p+7)-'0')*10 + (*(p+8)-'0');
	p=tokens[1+1];
	df = my_atof(p);
	degree = (int)(df/100);
	minute = (int)(df-degree*100);
	frac   = (int)((df-degree*100-minute)*1000);

	lat = degree*3600000 + minute*60000 + frac*60;

	if(*tokens[1+2] == 'S') {
		POSITION->CURRENT.LAT = -lat;
	}
	else if(*tokens[1+2] == 'N') {
		POSITION->CURRENT.LAT = lat;
	}
//GGA, 154126.000, 3625.8381, N, 12723.6518 ,E,1,08,1.2,74.89,M,0.00,M
	p=tokens[1+3];
	df = my_atof(p);
	degree = (int)(df/100);
	minute = (int)(df-degree*100);
	frac   = (int)((df-degree*100-minute)*1000);

	lon = degree*3600000 + minute*60000 + frac*60;

	if(*tokens[1+4] == 'W') {
		POSITION->CURRENT.LON = -lon;
	}
	else if(*tokens[1+4] == 'E') {
		POSITION->CURRENT.LON = lon;
	}
	p=tokens[1+8];
	hei = my_atof(p)*100;
	POSITION->CURRENT.HEI = hei;

	TRACK->TRACKED = atoi(tokens[1+6]);
	p=tokens[1+7];
	dop= my_atof(p)*10;
	TRACK->DOP = (short int)dop;

	if(TRACK->TRACKED)
	{
		EB->zero_tracking = 0;
	}
	else
	{
		if(SYSTEM.EB.ANTENNA == ANTENNA_OK)	EB->zero_tracking++;
		else EB->zero_tracking = 0;

	}


//	printf("\ntime:%2d %2d %2d> %2d %2d %2d\n"
//			,EB->TIME.YEAR,EB->TIME.MONTH, EB->TIME.DAY
//			,EB->TIME.HOUR, EB->TIME.MINUTE, EB->TIME.SECOND);

}

void nmea_unpack_gpgsa(char** tokens, int max_token)
{
	char c1,c2,c3,c4;
	int i,i1,i2,i3;

	EB_	*EB = &SYSTEM.EB;
	TS_	*TRACK = &SYSTEM.TRACK;
	POS_	*POSITION = &SYSTEM.POSITION;
	PHP_	*PHP = &SYSTEM.EB.PHP;

	int degree, minute, frac;
	long lat,lon;
	int dop;
	long int hei;

	i1=max_token-1;
	i2=i3=0;

	if(max_token < 2) {return;}
	if(*tokens[1+1] == '3'){
		fr_fixinfo = 3;
    	//EB->LOCKMODE = EB_3D_FIX;
    	EB->LOCKMODE = EB_LOCKED;
    	SYSTEM.TRACK.STATUS=wbD5; //3D fix
    	SYSTEM.TRACK.DOPTYPE = 0;
	}
	else if(*tokens[1+1] == '2'){
        EB->LOCKMODE = EB_LOCKED;
        SYSTEM.TRACK.STATUS=wbD4; //2D fix
        SYSTEM.TRACK.DOPTYPE=0;
		fr_fixinfo = 2;
	}
	else{
        SYSTEM.TRACK.STATUS=0; //2D fix
        SYSTEM.TRACK.DOPTYPE=0;
        EB->LOCKMODE = EB_UNLOCKED;
		fr_fixinfo = 1;
	}

	if( frc_error.gps ){
        SYSTEM.TRACK.STATUS=0; //2D fix
        SYSTEM.TRACK.DOPTYPE=0;
        EB->LOCKMODE = EB_UNLOCKED;
		fr_fixinfo = 1;
	}

	for(i=0;i<(max_token-2) && i<12; i++ )
	{
		TRACK->PRN_USED[i]=atoi(tokens[3+i]);
	}
	for(;i<12; i++ )
	{
		TRACK->PRN_USED[i]=0;
	}

}

int checkPRNused(int prn)
{
	int i;
	TS_	*TRACK = &SYSTEM.TRACK;
	for(i=0; i<12 ; i++ ){
		if( TRACK->PRN_USED[i] == prn && TRACK->PRN_USED[i]!=0 ) return 1;
	}
	return 0;
}

void nmea_unpack_gpgsv(char** tokens, int max_token)
{
	char c1,c2,c3,c4;
	int i1,i2,i3;

	EB_	*EB = &SYSTEM.EB;
	TS_	*TRACK = &SYSTEM.TRACK;
	POS_	*POSITION = &SYSTEM.POSITION;
	PHP_	*PHP = &SYSTEM.EB.PHP;

	int degree, minute, frac;
	long lat,lon;
	int dop;
	long int hei;

	i1=max_token-1;
	i2=i3=0;

	if(max_token < 5) {return;}


	c4 = atoi(tokens[1+0]);		//total number of sentence
	c1 = atoi(tokens[1+1]);		//current number of sentence
	TRACK->VISIBLE  = atoi(tokens[1+2]);		//total number of satellites in view
	//c3 = atoi(tokens[1+3]);		//visible number
	//c4 = atoi(tokens[1+4]);		//elevation
	//i3 = atoi(tokens[1+5]);		//AZ

	if	   (c1 == 1) c3 = 0; // index
	else if(c1 == 2) c3 = 4;
	else if(c1 == 3) c3 = 8;
	else if(c1 == 4) c3 = 12;
	else { printf("$GPGSV decoding warning!\n"); return ; }

	for(i2=0;i2<4 && i2<(max_token-4)/4;i2++)
	{
		TRACK->VIS_SAT[c3+i2].ID 		= atoi( tokens[ 4*(i2+1)   ] );
		TRACK->VIS_SAT[c3+i2].EL 		= atoi( tokens[ 4*(i2+1)+1 ] );
		TRACK->VIS_SAT[c3+i2].AZ 		= atoi( tokens[ 4*(i2+1)+2 ] );
		TRACK->VIS_SAT[c3+i2].HEALTH 	= atoi( tokens[ 4*(i2+1)+3 ] ); // C/N0
		/*if(TRACK->VIS_SAT[c3+i2].HEALTH != 0) sat_tracking++;*/
	}

	for(;i2<4;i2++)
	{
		TRACK->VIS_SAT[c3+i2].ID = 0;
		TRACK->VIS_SAT[c3+i2].EL = 0;
		TRACK->VIS_SAT[c3+i2].AZ = 0;
		TRACK->VIS_SAT[c3+i2].HEALTH = 0;
	}
	if( c1 == c4 ){

		i2 = c3+i2;
		for( ;i2<12;i2++){ // fill with zero to not assigned field.
			TRACK->VIS_SAT[c3+i2].ID = 0;
			TRACK->VIS_SAT[c3+i2].EL = 0;
			TRACK->VIS_SAT[c3+i2].AZ = 0;
			TRACK->VIS_SAT[c3+i2].HEALTH = 0;
		}

		for( i2 = 0; i2 < 12; i2++){
			TRACK->SAT[i2].ID 	= TRACK->VIS_SAT[i2].ID;
			if( checkPRNused(TRACK->VIS_SAT[i2].ID) ) TRACK->SAT[i2].MODE 	= 8;
			else TRACK->SAT[i2].MODE 	= 0;
			TRACK->SAT[i2].SS 	= TRACK->VIS_SAT[i2].HEALTH;
			TRACK->SAT[i2].STATUS = 0;
		}
	}
	SYSTEM.EB.once_receiver_detect = ON;
	SYSTEM.EB.TASK = OFF;
	SYSTEM.EB.RxCheckCounter = 0;

}

void CheckF1000cLock()
{

	char	parity_error;
	char	mode_error;

    int i,FaultCounter,LockCounter,sat_tracked;

    int j;
    unsigned int tt;

	char t1,t2,t3,t4,t5,t6,t7;

	char	holdover_condition;
	char	position_hold_plus;

	EB_	*EB = &SYSTEM.EB;
	TS_	*TRACK = &SYSTEM.TRACK;
	POS_	*POSITION = &SYSTEM.POSITION;
	PHP_	*PHP = &SYSTEM.EB.PHP;

	if( (VME.Data.TimeSync_Mode == VME_PTP_MODE) || (VME.Data.TimeSync_Mode == VME_ExtClock_MODE) ){
		ForceGPSTracked();
//		SetEbDummy();
	}

/*
   if( iCvValid < 0 )
	{
		iCvValid = -1;
		bCvValid = 0;
	}
	else bCvValid = 1;

	if( CONFIG.iCVType == 0 )//Master
	{
		if( timea.gps_status )  ForceGPSTracked();
		else 							ForceGPSUnTracked();
	}
	else//Slave
	{
		if( timea.gps_status && bCvValid )  ForceGPSTracked();
		else 							ForceGPSUnTracked();
	}

	iCvValid--;
*/
	if( CONFIG.iCVType == 0 )//Master
	{
		dbgCV(4) printf(
							"\r\n##>>valid:%s>> %3d %3d %3d"
							" (%.2f+(%.2f)) = %.2f, DAC:%.2f\r\n"
							,iCVType(), iCvValid, bCvValid, timea.gps_status
							, timea.offset*(double)1E7, CONFIG.SYSTEM_DELAY, timea.offset*(double)1E7+CONFIG.SYSTEM_DELAY, CONTROL.RealDAC
							);
	}
	else//Slave
	{
		dbgCV(4) printf(
							"\r\n##>>valid:%s>> %3d %3d %3d"
							" (%.2f+(%.2f)) = %.2f DAC:%.2f\r\n"
							,iCVType(), iCvValid, bCvValid, timea.gps_status
							, dbRlt_global, CONFIG.SYSTEM_DELAY, dbRlt_global+CONFIG.SYSTEM_DELAY, CONTROL.RealDAC
							);
	}




	if(SYSTEM.EB.STATUS != EB_STATUS_RUN){
		CHECKLOCK.LockedCounter = 0;
		CHECKLOCK.UnlockedCounter++;
   	}
	else {

		// Tracking
		if( TRACK->TRACKED == 0){
			tr1.unlock_counter++;
		}
dbgCV(127) printf("\n>>>%d, %d, %d\n",TRACK->TRACKED,TRACK->VISIBLE,SYSTEM.EB.LOCKMODE);
	    //if((SYSTEM.TRACK.TRACKED >= 2) && (SYSTEM.TRACK.VISIBLE > 0) && (sat_tracked >= 2) ){
	    if( TRACK->TRACKED >= 3 && TRACK->VISIBLE > 0 && SYSTEM.EB.LOCKMODE != EB_UNLOCKED ){
				eb_10min_start = 1;
				if(skipping_change_eb){skipping_change_eb = 0;}
	        	if( CHECKLOCK.LockedCounter < 20 )  CHECKLOCK.LockedCounter++ ;
	    }
	    else {
	        CHECKLOCK.LockedCounter = 0 ;
	    }

		if(CHECKLOCK.LockedCounter == 0 ){
	        CHECKLOCK.UnlockedCounter++;
		}
		else{
			if(FIRST_LOCK && SYSTEM.EB.STATUS == EB_STATUS_RUN) {
				if(CHECKLOCK.UnlockedCounter>0){
					TLogIt(TLog_No_Sat,CHECKLOCK.UnlockedCounter);
				}
			}

	        CHECKLOCK.UnlockedCounter = 0;
		}

	}

dbgCV(126) printf("\n>>>%d, %d\n",CHECKLOCK.LockedCounter,DIAG.EB);
	if((CHECKLOCK.LockedCounter >= 20) && (DIAG.EB != FAIL)) {

        //if(SYSTEM.EB.LOCKMODE != EB_LOCKED){
		if( SYSTEM.EB.LOCKMODE == EB_UNLOCKED ){
        	LogIt(LOG_CATA1_NORM, LOG_CATA2_OK, LOG_GPS_Lock,SYSTEM.EB.LOCKMODE);
        }

        SYSTEM.EB.LOCKMODE = EB_LOCKED;
		gps_holdover_counter = 0;
		gps_detect_flag = ON;

		if(LOCK_REFERENCE){ gps_lock_flag = ON;	}
	}
	else {

		gps_holdover_counter++;

        if(gps_holdover_counter > 89){
        	if(SYSTEM.EB.LOCKMODE != EB_UNLOCKED){
        		LogIt(LOG_CATA1_NORM, LOG_CATA2_WARN, LOG_GPS_Unlock,0);
        	}
        	SYSTEM.EB.LOCKMODE = EB_UNLOCKED;
        }


	}



	holdover_condition = is_holdover_condition();

//	if( (REFERENCE_MODE == UNDEFINED) /* || (holdover_condition == HOLDOVER_OVER10MIN) */) {

	//if((SYSTEM.EB.STATUS == EB_STATUS_RUN) && (SYSTEM.EB.LOCKMODE == EB_LOCKED)){
	if((gps_detect_flag == ON) && (gps_holdover_counter <= Holdover_limit)){
		if(REFERENCE_MODE != EB_STATUS_RUN){
			REFERENCE_MODE = EB_STATUS_RUN;
			Select1PPSEb();

			CONTROL.SYNC = ON;
			control_sync_type = 3;
		}
	}

    if (SYSTEM.IO.CTRL_PORT.MODE == UDEBUG){

		if(LOCK_REFERENCE){		t1 = 'Y';		}
		else {					t1 = 'N';		}

		if(SYSTEM.OPERATION.LOCKMODE == LOCKED){		t2 = 'L';		}
		else {					t2 = 'H';		}

		//if(REFERENCE_MODE == EB_STATUS_RUN){		t3 = 'G';		}
		//else if(REFERENCE_MODE == LMU_STATUS_RUN){		t3 = 'L';		}
		//else if(REFERENCE_MODE == E1_STATUS_RUN){		t3 = 'E';		}
		//else if(REFERENCE_MODE == E2_STATUS_RUN){		t3 = 'e';		}
		//else {					t3 = '.';		}

		if(DIAG.EB_LOCK == OK){t3='L';}
		else{t3='U';}

		if((SYSTEM.EB.STATUS == EB_STATUS_RUN) && (SYSTEM.EB.LOCKMODE == EB_LOCKED)){ 	t4 = 'Y';}
		else {																			t4 = 'N';}

       	if(t4 == 'N') {
       		sprintf((char*)MESG,"<%c[7mG:%c,%c,v:%d,t:%d,%d(%d,%d,%d,d:%d,%d)%c[0m>",
       			0x1B, t4, t3, SYSTEM.TRACK.VISIBLE, SYSTEM.TRACK.TRACKED, CHECKLOCK.LockedCounter
       			,(int)SYSTEM.EB.STATUS, (int)SYSTEM.EB.LOCKMODE,(int)gps_detect_flag ,(int)DIAG.EB ,CHECKLOCK.UnlockedCounter
       			, 0x1B);
       	}
       	else {
       		sprintf((char*)MESG,"<G:%c,%c,v:%d,t:%d,%d>",
       			t4, t3,SYSTEM.TRACK.VISIBLE, SYSTEM.TRACK.TRACKED, CHECKLOCK.LockedCounter);
       	}
        if (SYSTEM.IO.CTRL_PORT.MODE == UDEBUG){TransmitMessage((BYTE*)MESG,DEBUG_PORT); }
    }

	holdover_condition = is_holdover_condition();

    switch(SYSTEM.OPERATION.LOCKMODE){
        case    LOCKED:

                    CHECKLOCK.HoldoverCounter = 0;

                    if(holdover_condition != LOCKED ){
                        SYSTEM.OPERATION.LOCKMODE = holdover_condition;
                    }

                    if( CHECKLOCK.HoldoverDelayCounter > 0 ){
                     	CHECKLOCK.HoldoverDelayCounter--;
                    }
                    break;

        case    HOLDOVER:
        case    UNLOCKED:
        case	HOLDOVER_OVER10MIN:

                    CHECKLOCK.HoldoverCounter++;

                    if(holdover_condition == LOCKED){
                    //if(IsRefLocked()){
                    //if( CHECKLOCK.LockedCounter == 20 ){
                        SYSTEM.OPERATION.LOCKMODE = LOCKED;

                        if( CHECKLOCK.HoldoverCounter > 90 ){
                        	CHECKLOCK.HoldoverDelayCounter = 90;
                        }
                        else{
                        	CHECKLOCK.HoldoverDelayCounter = CHECKLOCK.HoldoverCounter;
                        }

						if( FIRST_LOCK /* && (SYSTEM.OPERATION.CTRLMODE == CTRL_LOCKEDtoGPS)*/ ){
							RECOVERY.flag = ON;
							RECOVERY.IntervalCounter = 0;
							//RECOVERY.wait_time = 30;
							//RECOVERY.average_time = 30;
							RECOVERY.wait_time = 100;
							RECOVERY.average_time = 100;
						}
                    }

					else {
						SYSTEM.OPERATION.LOCKMODE = holdover_condition;
					}

                    break;
    }
}

int bOnceForceGPSTracked = 0;
void ForceGPSTracked()
{
	TS_	*TRACK = &SYSTEM.TRACK;
	EB_	*EB = &SYSTEM.EB;

	EB->STATUS = EB_STATUS_RUN;//Sewon

	TRACK->TRACKED = 8;
	TRACK->VISIBLE  = 8;
 	SYSTEM.EB.LOCKMODE = EB_LOCKED;
 	bOnceForceGPSTracked = 1;

 	rb.sro100.quality = YES;
 	rb.comm_ready	= YES;
}

void ForceGPSUnTracked()
{
	TS_	*TRACK = &SYSTEM.TRACK;
	EB_	*EB = &SYSTEM.EB;

	if(bOnceForceGPSTracked ) return ;

	EB->STATUS = EB_STATUS_RUN;//Sewon

	TRACK->TRACKED =  0;
	TRACK->VISIBLE  = 0;
 	SYSTEM.EB.LOCKMODE = UNLOCKED;
}
void ForceEBRun()
{
	EB_	*EB = &SYSTEM.EB;

	SYSTEM.TIME.LEAPSECOND = 16;
		EB->almanac_step = EB_SET_LEAPSECOND;
		EB->STATUS = EB_STATUS_RUN;
		EB->TASK = OFF;
		EB->LockedCounter = 0;
//		CONTROL.SURVEYSTEP = Survey_UpdateDetailTable;//Sewon
		SYSTEM.TIME.Valid=OK;

		EB->once_receiver_detect = ON;

		MessageOut("EB-RUN\r\n");
		ForceGPSTracked();

}
